import matplotlib
import pandas as pd
import matplotlib.pyplot as plt
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
import mplfinance as mpf

from binance.client import Client
from datetime import datetime, timedelta

from matplotlib import font_manager


# 1. 获取Binance数据
def get_binance_data(symbol='BTCUSDT', interval='1d', days=30):
    proxies = {
        'http': 'socks5://127.0.0.1:10010',
        'https': 'socks5://127.0.0.1:10010',
    }
    # 初始化Binance客户端 (不需要API密钥获取K线数据)
    client = Client(requests_params={'proxies': proxies, 'timeout': 10})

    # 计算开始和结束时间
    end_date = datetime.now()
    start_date = end_date - timedelta(days=days)

    # 获取K线数据
    klines = client.get_historical_klines(
        symbol=symbol,
        interval=interval,
        start_str=start_date.strftime('%Y-%m-%d'),
        end_str=end_date.strftime('%Y-%m-%d')
    )

    # 转换为DataFrame
    df = pd.DataFrame(klines, columns=[
        'Open time', 'Open', 'High', 'Low', 'Close', 'Volume',
        'Close time', 'Quote asset volume', 'Number of trades',
        'Taker buy base asset volume', 'Taker buy quote asset volume', 'Ignore'
    ])

    # 转换数据类型
    df['Open time'] = pd.to_datetime(df['Open time'], unit='ms')
    df['Close time'] = pd.to_datetime(df['Close time'], unit='ms')
    df = df.astype({
        'Open': float, 'High': float, 'Low': float, 'Close': float,
        'Volume': float
    })

    # 设置索引
    df.set_index('Open time', inplace=True)

    return df[['Open', 'High', 'Low', 'Close', 'Volume']]

# 2. 获取数据
symbol = 'BTCUSDT'
interval = '1d'  # 1天间隔
data = get_binance_data(symbol=symbol, interval=interval, days=90)

# 3. 创建K线图
fig, axes = mpf.plot(
    data,
    type='candle',
    style='charles',
    title=f'{symbol} {interval} K线图',
    ylabel='价格 ($)',
    volume=True,
    returnfig=True
)

# 4. 添加鼠标移动事件处理
def on_mouse_move(event):
    if event.inaxes == axes[0]:  # 确保鼠标在主图表区域
        x = event.xdata
        y = event.ydata

        # 找到最近的K线索引
        idx = int(round(x))
        if 0 <= idx < len(data):
            current = data.iloc[idx]
            open_price = current['Open']
            close_price = current['Close']
            change = (close_price - open_price) / open_price * 100

            # 计算最高最低涨跌幅
            high = current['High']
            low = current['Low']
            high_change = (high - open_price) / open_price * 100
            low_change = (low - open_price) / open_price * 100

            # 移除旧的注释
            if hasattr(on_mouse_move, 'annot'):
                on_mouse_move.annot.remove()

            # 创建新的注释框
            date_str = data.index[idx].strftime('%Y-%m-%d')
            text = (f"日期: {date_str}\n"
                    f"开盘: {open_price:.2f}\n"
                    f"收盘: {close_price:.2f} ({change:+.2f}%)\n"
                    f"最高: {high:.2f} ({high_change:+.2f}%)\n"
                    f"最低: {low:.2f} ({low_change:+.2f}%)")

            on_mouse_move.annot = axes[0].annotate(
                text,
                xy=(x, y),
                xytext=(10, 10),
                textcoords='offset points',
                bbox=dict(boxstyle='round,pad=0.5', fc='yellow', alpha=0.8),
                arrowprops=dict(arrowstyle='->')
            )
            fig.canvas.draw_idle()

# 连接鼠标事件
fig.canvas.mpl_connect('motion_notify_event', on_mouse_move)
# 0. 首先设置中文字体（必须在所有绘图操作之前）
matplotlib.rcParams['font.family'] = 'SimHei'  # 或其他支持中文的字体
matplotlib.rcParams['axes.unicode_minus'] = False
# 5. 显示图表
plt.tight_layout()
plt.show()